/*
 * @Author: zxc
 * @Date: 2020-11-29 13:49:35
 * @LastEditTime: 2020-11-29 16:02:49
 * @LastEditors: zxc
 * @Description:
 */
import * as glob from "glob"
import * as Koa from "koa"
import * as KoaRouter from "koa-router"

type HTTPMethod = "get" | "put" | "del" | "post" | "patch"

interface LoadOptions {
  // 路由文件扩展名
  extname?: string
}

interface RouteOptions {
  // 特殊请求，用于单独定制前缀
  prefix?: string
  // 为当前路由添加一个或多个中间件
  middlewares?: Array<Koa.Middleware>
}
const router = new KoaRouter()

export const decorate = (
  method: HTTPMethod,
  path: string,
  options: RouteOptions = {},
  router: KoaRouter
) => {
  return (target, property: string) => {
    // 异步执行
    process.nextTick(() => {
      // 添加中间件数组
      const middlewares = []

      if (options.middlewares) {
        middlewares.push(...options.middlewares)
      }

      if (target.middlewares) {
        middlewares.push(...target.middlewares)
      }

      middlewares.push(target[property])

      const url = options && options.prefix ? options.prefix + path : path
      router[method](url, ...middlewares)
    })
  }
}

export const method = method => (path: string, options?: RouteOptions) =>
  decorate(method, path, options, router)

export const get = method("get")
export const post = method("post")
export const put = method("put")
export const del = method("del")
export const patch = method("patch")

export const loader = (
  folder: string,
  options: LoadOptions = {}
): KoaRouter => {
  const extname = options.extname || ".{js,ts}"
  glob
    .sync(require("path").join(folder, `./**/*${extname}`))
    .forEach(item => require(item))
  return router
}

export const middlewares = (middlewares: Koa.Middleware[]) => {
  return function (target) {
    target.prototype.middlewares = middlewares
  }
}
